package drp.snowbell.part;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import drp.snowbell.annotation.APart;
import drp.snowbell.annotation.AProperty;

import weibo.toyger.common.util.StrHelper;
import weibo.toyger.core.beans.IEntity;
import weibo.toyger.core.data.IStorage;
import weibo.toyger.core.data.ITransaction;
import weibo.toyger.core.data.StorageManager;
import weibo.toyger.core.data.expression.ExpUtil;
import weibo.toyger.core.data.expression.IExp;
import weibo.toyger.core.exception.PropertyNeedRequiredException;
import weibo.toyger.core.exception.PropertyNotExistException;
import weibo.toyger.core.farm.Dna;
import weibo.toyger.core.farm.Farm;
import weibo.toyger.core.farm.Property;


/**
 * 树.如果需要自动更新层信息(包括所有子元素的层信息)需要使用{@link #setParent(IEntity)} 方法.
 * 
 * @author jimmy
 * 
 */
@APart(name = LevelTree.SKILL_NAME)
public class LevelTree extends PartBase {
	public final static String SKILL_NAME = "Tree";
	// public final static String PROP_PARENT_VALUE = "ParentValue"; // 属性名称

	@AProperty
	private String parentValue;
	@AProperty
	private String level1;
	@AProperty
	private String level2;
	@AProperty
	private String level3;
	@AProperty
	private String level4;
	@AProperty
	private String level5;
	@AProperty
	private String level6;

	private PartBlueprint sdna;
	private IEntity parent;
	private Property levelProperty;
	private boolean isChangeParent = false;
	private int oldLevel = 0;
	private ITransaction trans;

	public void onSaveStart() {
		if (isChangeParent) {
			IEntity entity = getTbean();
			if (!StrHelper.isNullOrEmpty(entity.getId())) {
				// 如果不是插数据, 需要自动更新所有子元素的层信息
				String entityName = entity.getBeanName();
				IExp where = getLevelWhere(getTbean());
				Map<Property, Object> map = new LinkedHashMap<Property, Object>();// 保持顺序
				PartBlueprint sd = getSkillDna();
				// map.put(sd.getProperty("ParentValue"), getParentValue());
				int level = getCurrentLevel();
				// int sub = level - oldLevel;
				int j = oldLevel;
				for (int i = level + 1; i <= 6; i++) {
					j++;
					Property propLevel = sd.getProperty("Level" + i);
					if (j <= 6) {
						Property oldPropLevel = sd.getProperty("Level" + j);
						map.put(propLevel, oldPropLevel);
					} else {
						map.put(propLevel, null);
					}
				}
				for (int i = 1; i <= level; i++) {
					Property propLevel = sd.getProperty("Level" + i);
					Object value = entity.getValue(propLevel);
					map.put(propLevel, value);
				}

				if (map.size() > 0) {
					IStorage<IEntity> storage = StorageManager.getCurrentStorage(entityName);
					trans = storage.beginTransaction();
					storage.batchUpdate(map, where);
				}
			}
		}
	}

	public void onSaveEnd() {
		if (trans != null) {
			trans.commit();// 提交事务
			trans = null;
		}
	}

	/**
	 * 获取直系的子节点
	 * 
	 * @return
	 */
	public List<? extends IEntity> getDirectChildren() {
		IEntity entity = getTbean();
		String entityName = entity.getBeanName();
		PartBlueprint sd = getSkillDna();
		Property prop = sd.getProperty("ParentValue");
		Object value = entity.getBasicValue(getLevelProp());
		IExp where = ExpUtil.getPvEqExp(prop, value);
		IStorage<IEntity> storage = StorageManager.getCurrentStorage(entityName);
		List<IEntity> list = storage.getList(where);
		return list;
	}

	/**
	 * 获取所有的子节点,包括子节点的子节点
	 * 
	 * @return
	 */
	public List<? extends IEntity> getAllChildren() {
		int nLevel = getCurrentLevel();
		if (nLevel >= 6) {
			// 最低级别,没有子元素
			return Collections.emptyList();
		}
		IEntity entity = getTbean();
		String entityName = entity.getBeanName();
		IExp where = getLevelWhere(entity);
		IStorage<IEntity> storage = StorageManager.getCurrentStorage(entityName);
		List<IEntity> list = storage.getList(where);
		return list;
	}

	@Override
	public String getSkillName() {
		return SKILL_NAME;
	}

	/**
	 * 获取当前的树的级别,根返回0,最大级别为6
	 * 
	 * @return
	 */
	public int getCurrentLevel() {
		if (getLevel1() == null) {
			return 0;
		} else if (getLevel2() == null) {
			return 1;
		} else if (getLevel3() == null) {
			return 2;
		} else if (getLevel4() == null) {
			return 3;
		} else if (getLevel5() == null) {
			return 4;
		} else if (getLevel6() == null) {
			return 5;
		} else {
			return 6;
		}
	}

	public void setParentValue(String parentValue) {
		this.parentValue = parentValue;
	}

	public String getParentValue() {
		return parentValue;
	}

	public void setLevel1(String level1) {
		this.level1 = level1;
	}

	public String getLevel1() {
		return level1;
	}

	public void setLevel2(String level2) {
		this.level2 = level2;
	}

	public String getLevel2() {
		return level2;
	}

	public void setLevel3(String level3) {
		this.level3 = level3;
	}

	public String getLevel3() {
		return level3;
	}

	public void setLevel4(String level4) {
		this.level4 = level4;
	}

	public String getLevel4() {
		return level4;
	}

	public void setLevel5(String level5) {
		this.level5 = level5;
	}

	public String getLevel5() {
		return level5;
	}

	public void setLevel6(String level6) {
		this.level6 = level6;
	}

	public String getLevel6() {
		return level6;
	}

	/**
	 * 设置父节点.如果为null表示为根节点.并设置所有的level
	 * 
	 * @param parent
	 */
	public void setParent(IEntity parent) {
		if (parent == null) {
			this.parent = parent;
			if (!StrHelper.isNullOrEmpty(getParentValue())) {
				setParentValue(null);
				oldLevel = getCurrentLevel();
				isChangeParent = true;
			}
		} else {
			LevelTree parentTree = (LevelTree) parent.getPart(getSkillName());
			if (parentTree != null) {
				this.parent = parent;
				String unique = getParentValue();
				String parentValue = (String) parent.getValue(getLevelProp());
				if (parentValue != null) {
					if (parentValue.equals(unique)) {
						// 如果相等直接返回
						return;
					}
				} else {
					return;
				}
				oldLevel = getCurrentLevel();
				setParentValue(parentValue);
				isChangeParent = true;
				int parentLevel = parentTree.getCurrentLevel();
				switch (parentLevel) {
				case 0:
					this.setLevel1(parentValue);
					this.setLevel2(null);
					this.setLevel3(null);
					this.setLevel4(null);
					this.setLevel5(null);
					this.setLevel6(null);
					break;
				case 1:
					this.setLevel1(parentTree.getLevel1());
					this.setLevel2(parentValue);
					this.setLevel3(null);
					this.setLevel4(null);
					this.setLevel5(null);
					this.setLevel6(null);
					break;
				case 2:
					this.setLevel1(parentTree.getLevel1());
					this.setLevel2(parentTree.getLevel2());
					this.setLevel3(parentValue);
					this.setLevel4(null);
					this.setLevel5(null);
					this.setLevel6(null);
					break;
				case 3:
					this.setLevel1(parentTree.getLevel1());
					this.setLevel2(parentTree.getLevel2());
					this.setLevel3(parentTree.getLevel3());
					this.setLevel4(parentValue);
					this.setLevel5(null);
					this.setLevel6(null);
					break;
				case 4:
					this.setLevel1(parentTree.getLevel1());
					this.setLevel2(parentTree.getLevel2());
					this.setLevel3(parentTree.getLevel3());
					this.setLevel4(parentTree.getLevel4());
					this.setLevel5(parentValue);
					this.setLevel6(null);
					break;
				case 5:
					this.setLevel1(parentTree.getLevel1());
					this.setLevel2(parentTree.getLevel2());
					this.setLevel3(parentTree.getLevel3());
					this.setLevel4(parentTree.getLevel4());
					this.setLevel5(parentTree.getLevel5());
					this.setLevel6(parentValue);
					break;
				case 6:
					// TODO 报错.不能添加子节点
					break;

				}
			}
		}
	}

	public IEntity getParent() {
		if (parent == null) {
			String unique = getParentValue();
			if (unique != null) {
				IEntity entity = getTbean();
				if (entity != null) {
					String entityName = entity.getBeanName();
					if (!StrHelper.isNullOrEmpty(entityName)) {
						IStorage<IEntity> storage = StorageManager.getCurrentStorage(entityName);
						parent = storage.loadWithProp(getLevelProp(), unique);
					}
				}
			}
		}
		return parent;
	}

	/**
	 * 从配置里获取作为layer的属性
	 * 
	 * @return
	 */
	private Property getLevelProp() {
		if (levelProperty == null) {
			IEntity entity = getTbean();
			String entityName = entity.getBeanName();
			Dna dna = Farm.getDna(entityName);

			String param = getParameter();
			if (StrHelper.isNullOrEmpty(param)) {
				levelProperty = dna.getIdProperty();
			} else {
				Property prop = dna.getProperty(param);
				if (prop != null) {
					if (prop.isRequired()) {
						levelProperty = prop;
					} else {
						throw new PropertyNeedRequiredException(prop);
					}
				}
			}
		}
		if (levelProperty == null) {
			throw new PropertyNotExistException(getParameter());
		}
		return levelProperty;
	}

	private PartBlueprint getSkillDna() {
		if (sdna == null) {
			IEntity entity = getTbean();
			if (entity != null) {
				String entityName = entity.getBeanName();
				sdna = PartManager.getSkillDna(entityName, getSkillName());
			}
		}
		return sdna;
	}

	private static IExp getLevelWhere(IEntity entity) {
		LevelTree tree = (LevelTree) entity.getPart(SKILL_NAME);
		int nLevel = tree.getCurrentLevel();
		IExp where = null;
		PartBlueprint sd = PartManager.getSkillDna(entity.getBeanName(), SKILL_NAME);
		Object value = entity.getBasicValue(tree.getLevelProp());

		if (nLevel == 0) {
			where = ExpUtil.getPvEqExp(sd.getProperty("Level1"), value);
		} else if (nLevel == 1) {
			where = ExpUtil.getPvEqExp(sd.getProperty("Level2"), value);
		} else if (nLevel == 2) {
			where = ExpUtil.getPvEqExp(sd.getProperty("Level3"), value);
		} else if (nLevel == 3) {
			where = ExpUtil.getPvEqExp(sd.getProperty("Level4"), value);
		} else if (nLevel == 4) {
			where = ExpUtil.getPvEqExp(sd.getProperty("Level5"), value);
		} else if (nLevel == 5) {
			where = ExpUtil.getPvEqExp(sd.getProperty("Level6"), value);
		}
		return where;
	}
}
